package com.example.ddz.framework.impl;

/**
 * Created by IntelliJ IDEA.
 * User: Marcel Melzig
 * Date: 27.07.11
 * Time: 19:43
 */

import java.util.ArrayList;
import java.util.List;

import android.view.MotionEvent;
import android.view.View;

import com.example.ddz.framework.IInput.TouchEvent;
import com.example.ddz.framework.ITouchHandler;
import com.example.ddz.framework.Pooling;
import com.example.ddz.framework.Pooling.PoolObjectFactory;

/**
 * The class handles the single touch events.
 */
public class SingleTouchHandler implements ITouchHandler
{
    private boolean isTouched;
    private int touchX;
    private int touchY;
    private final Pooling<TouchEvent> touchEventPool;
    private final List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();
    private final List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>();

    /**
     * Creates an instance of this class and
     *
     * @param view The view which fires the touch event.
     */
    public SingleTouchHandler(View view)
    {
        PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>()
        {
            @Override
            public TouchEvent createObject()
            {
                return new TouchEvent();
            }
        };
        touchEventPool = new Pooling<TouchEvent>(factory, 100);
        view.setOnTouchListener(this);
    }

    /**
     * This method handles the event.
     *
     * @param v     The given view.
     * @param event The motion event.
     * @return True if the view is touched, otherwise false.
     */
    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        synchronized (this)
        {
            TouchEvent touchEvent = touchEventPool.NewObject();
            switch (event.getAction())
            {
                case MotionEvent.ACTION_DOWN:
                    touchEvent.type = TouchEvent.TOUCH_DOWN;
                    isTouched = true;
                    break;
                case MotionEvent.ACTION_MOVE:
                    touchEvent.type = TouchEvent.TOUCH_DRAGGED;
                    isTouched = true;
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    touchEvent.type = TouchEvent.TOUCH_UP;
                    isTouched = false;
                    break;
            }
            touchEvent.x = touchX = (int) (event.getX());
            touchEvent.y = touchY = (int) (event.getY());
            touchEventsBuffer.add(touchEvent);
            return true;
        }
    }

    /**
     * The touch down state of the given pointer.
     *
     * @param pointer The pointer of the event.
     * @return True if the pointer is touched down, otherwise false.
     */
    @Override
    public boolean IsTouchDown(int pointer)
    {
        synchronized (this)
        {
            return pointer == 0 && isTouched;
        }
    }

    /**
     * Gets the x value of the given pointer.
     *
     * @param pointer The pointer of the event.
     * @return The x value of the given pointer.
     */
    @Override
    public int GetTouchX(int pointer)
    {
        synchronized (this)
        {
            return touchX;
        }
    }

    /**
     * Gets the y value of the given pointer.
     *
     * @param pointer The pointer of the event.
     * @return The y value of the given pointer.
     */
    @Override
    public int GetTouchY(int pointer)
    {
        synchronized (this)
        {
            return touchY;
        }
    }

    /**
     * Gets the list of touch events stored in the pool.
     *
     * @return The list of cached touch events.
     */
    @Override
    public List<TouchEvent> GetTouchEvents()
    {
        synchronized (this)
        {
            for (TouchEvent touchEvent : touchEvents)
                touchEventPool.Free(touchEvent);

            touchEvents.clear();
            touchEvents.addAll(touchEventsBuffer);
            touchEventsBuffer.clear();
            return touchEvents;
        }
    }
}
